﻿using DLL.NET.DB.MS.Drugs.CRUD.Repository;

using DLL.NET50.DB.PIVAS.Entitys.DTO;
using DLL.NET50.DB.PIVAS.ORM.Repository;
using DLL.NET60.DB.MS.Entity.DTO;
using DLL.Standard.Infrastructure.Log;
using System;
using System.Collections.Generic;
using System.Linq;

namespace DLL.NET50.DB.MS.AdviceAndDrug.ORM.Repository
{
    public interface IAdviceAndDicDrugsRepository
    {
        //提前加载数据
        void LoadData();

        /// <summary>
        /// 根据瓶贴号编码，获取医嘱和药品
        /// </summary>
        /// <param name="barCode"></param>
        /// <returns></returns>
        CMS_AdviceAndDrug GetAdviceAndDrug(string barCode);

        /// <summary>
        /// 根据瓶贴号，获取医嘱数量
        /// </summary>
        /// <param name="barCode"></param>
        /// <returns></returns>
        int GetAdviceCount(string barCode);

        /// <summary>
        /// 获取总的医嘱数量
        /// </summary>
        /// <returns></returns>
        int GetAllAdviceCount();

        List<DTO_adi_dic_drug> GetDrugByCode(string drugCode);

        CDrugCodes GetAllDrugCode(string barCode);

        CDrugCodes GetLoacalNotExistDrugCodes(string barCode);

        List<string> GetAllDrugCodeByBarCode(string barCode);

        List<string> GetNotExistDrugByBarCode(string barCode);
    }

    public class CAdviceAndDicDrugsRepository : IAdviceAndDicDrugsRepository
    {
        protected IAdviceDrugRepository _adviceDrug;
        protected IAdviceExecuteRepository _adviceExecute;
        protected IMSDrugsRepository _drugsRepository;

        public CAdviceAndDicDrugsRepository(IAdviceDrugRepository adviceDrug,
            IAdviceExecuteRepository adviceExecute,
            IMSDrugsRepository drugsRepository)
        {
            _adviceDrug = adviceDrug;
            _adviceExecute = adviceExecute;
            _drugsRepository = drugsRepository;
        }

        public void LoadData()
        {
            _adviceExecute.GetAll();
            _adviceDrug.GetAll();
            _drugsRepository.GetAll();
        }

        public CMS_AdviceAndDrug GetAdviceAndDrug(string barCode)
        {
            CMS_AdviceAndDrug adviceAndDrug = new CMS_AdviceAndDrug();
            try
            {
                List<DTO_adi_advice_execute> rlpivasAdvicePatient = _adviceExecute.GetAdviceExcuteByBottleNum(barCode);
                List<DTO_adi_advice_execute> lpivasAdvicePatient = rlpivasAdvicePatient.Distinct(new AdvicePatientItemEqualityComparer()).ToList();
                if (lpivasAdvicePatient.Count == 1)
                {
                    adviceAndDrug.pivasAdvicePatient = lpivasAdvicePatient[0];
                    //获取医嘱药品单
                    List<DTO_adi_advice_drug> rlPivasAdvice = _adviceDrug.GetAdviceDrugByGroupNo(barCode);
                    List<DTO_adi_advice_drug> lPivasAdvice = rlPivasAdvice.Distinct(new AdviceDrugItemEqualityComparer()).ToList();
                    if (lPivasAdvice.Count > 1)
                    {
                        adviceAndDrug.pivasAdviceDrugs = lPivasAdvice;
                        for (int i = 0; i < lPivasAdvice.Count; i++)
                        {
                            DTO_adi_advice_drug adviceDrug = lPivasAdvice[i];
                            string drugcode = adviceDrug.DRUG_CODE.Trim();
                            List<DTO_adi_dic_drug> ldrug = _drugsRepository.SearchDrugsByDrugCode(drugcode);
                            if (1 == ldrug.Count)
                            {
                                //判断药品属性是否设置
                                DTO_adi_dic_drug drug = ldrug[0];
                                if (drug.SOLVENT_FLAG != null)
                                {
                                    if (drug.SOLVENT_FLAG == 1)
                                    {
                                        //是溶媒
                                        adviceAndDrug.Solvent = drug;
                                        adviceAndDrug.adviceSolvent = adviceDrug;
                                    }
                                    else
                                    {
                                        //是药
                                        bool ret = CDrugInitialize.PropertyIsSet(drug);
                                        if (true == ret)
                                        {
                                            if (drug.BOTTLE_TYPE == 0)
                                            {
                                                //是西林瓶的药则添加，如果是安瓿瓶的则不要
                                                if ((adviceDrug.DOSE_UNIT.Trim() == "BO") || (adviceDrug.DOSE_UNIT.Trim() == "bo"))
                                                {
                                                    adviceDrug.REALDOSE = drug.DOSE * Convert.ToSingle(adviceDrug.REAL_QUANTITY);
                                                    adviceDrug.DOSE_UNIT = drug.DOSE_UNIT;
                                                }

                                                if ((drug.DOSE_UNIT.Trim().ToUpper() == "G") || (drug.DOSE_UNIT.Trim().ToUpper() == "MG"))
                                                {
                                                    //单位是g 或mg
                                                    adviceAndDrug.Drugs.Add(drug);
                                                    adviceAndDrug.adviceDrug.Add(adviceDrug);
                                                }
                                                else
                                                {
                                                    //单位不是g
                                                    if (drug.DOSE_UNIT.Trim() != adviceDrug.DOSE_UNIT.Trim())
                                                    {
                                                        adviceAndDrug.Info = "药品编码=" + drugcode + ",医嘱里面的单位，和药品字典里面的单位不一致，无法配药！";
                                                        adviceAndDrug.DrugCode = drugcode;
                                                        adviceAndDrug.reValue = 0;
                                                        LogHelper.Warn(adviceAndDrug.Info);
                                                        return adviceAndDrug;
                                                    }
                                                    else
                                                    {
                                                        adviceAndDrug.Drugs.Add(drug);
                                                        adviceAndDrug.adviceDrug.Add(adviceDrug);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            //药品属性没有设置
                                            adviceAndDrug.Info = "药品编码=" + drugcode + ",药品属性没有设置！";
                                            adviceAndDrug.DrugCode = drugcode;
                                            adviceAndDrug.reValue = 0;
                                            LogHelper.Warn(adviceAndDrug.Info);
                                            return adviceAndDrug;
                                        }
                                    }
                                }
                                else
                                {
                                    adviceAndDrug.Drugs.Add(drug);
                                    adviceAndDrug.Info = "药品编码=" + drugcode + ",药品的溶媒属性没有设置！";
                                    adviceAndDrug.DrugCode = drugcode;
                                    adviceAndDrug.reValue = 0;
                                    return adviceAndDrug;
                                }
                            }
                            else
                            {
                                adviceAndDrug.Info = "药品编码=" + drugcode + ",药品字典中不存在该药品！";
                                adviceAndDrug.DrugCode = drugcode;
                                adviceAndDrug.reValue = 0;
                                LogHelper.Warn(adviceAndDrug.Info);
                                return adviceAndDrug;
                            }
                        }
                    }
                    else
                    {
                        adviceAndDrug.Info = "无效条码";
                        adviceAndDrug.reValue = 0;
                        LogHelper.Warn("DTO_adi_advice_drug不存在该条码：" + barCode);
                        return adviceAndDrug;
                    }
                }
                else
                {
                    if (lpivasAdvicePatient.Count < 1)
                    {
                        LogHelper.Warn("数据库中不存在该医嘱：" + barCode);
                    }
                    else
                    {
                        LogHelper.Warn("数据库中医嘱存在重复：" + barCode);
                    }
                    adviceAndDrug.Info = "医嘱号=" + barCode + ",无效医嘱";
                    adviceAndDrug.reValue = 0;
                    return adviceAndDrug;
                }
                adviceAndDrug.Info = "正常";
                adviceAndDrug.reValue = 1;
            }
            catch (Exception e)
            {
                adviceAndDrug.Info = "获取医嘱和药品字典出现异常:" + e.Message;
                adviceAndDrug.reValue = -1;
                LogHelper.Warn(adviceAndDrug.Info);
            }
            try
            {
                //添加判断有没有溶媒
                if (adviceAndDrug.Solvent.SOLVENT_FLAG == null)
                {
                    adviceAndDrug.Info = "医嘱中没有溶媒，请确认溶媒药品属性设置是否错误！";
                    adviceAndDrug.reValue = 0;
                    LogHelper.Warn(adviceAndDrug.Info);
                    return adviceAndDrug;
                }
                if (adviceAndDrug.Drugs.Count > 1)
                {
                    //对药进行排序
                    //List<DTO_adi_dic_drug> copyedDrugs = adviceAndDrug.Drugs.OrderBy(o => o.BOTTLE_VOLUME).ToList();
                    List<DTO_adi_advice_drug> coppyedAdvicedrugs = new List<DTO_adi_advice_drug>(adviceAndDrug.adviceDrug);
                    //copyedDrugs.Sort((a, b) => a.BOTTLE_VOLUME.CompareTo(b.BOTTLE_VOLUME));
                    //List<DTO_adi_dic_drug> soredDrugs = bubbleSort(copyedDrugs);
                    List<DTO_adi_dic_drug> soredDrugs = adviceAndDrug.Drugs.OrderBy(o => o.BOTTLE_VOLUME).ToList();
                    for (int i = 0; i < soredDrugs.Count; i++)
                    {
                        string drugCode = soredDrugs[i].DRUG_CODE.Trim();
                        DTO_adi_advice_drug ad = adviceAndDrug.adviceDrug.Where(c => c.DRUG_CODE.Trim() == drugCode.Trim()).First();
                        coppyedAdvicedrugs[i] = ad;
                        adviceAndDrug.DrugCountOfOneType.Add(Convert.ToInt32(ad.QUANTITY));
                    }
                    adviceAndDrug.Drugs = soredDrugs;
                    adviceAndDrug.adviceDrug = coppyedAdvicedrugs;
                }
                else
                {
                    adviceAndDrug.DrugCountOfOneType.Add(Convert.ToInt32(adviceAndDrug.adviceDrug[0].QUANTITY));
                }
            }
            catch (Exception e)
            {
                LogHelper.Warn("GetAdviceAndDrug:函数出现异常" + e.Message);
            }
            return adviceAndDrug;
        }

        public CDrugCodes GetAllDrugCode(string barCode)
        {
            CDrugCodes _drugCodes = new CDrugCodes();
            try
            {
                List<DTO_adi_advice_drug> lPivasAdvice = _adviceDrug.GetAdviceDrugByGroupNo(barCode);
                if (lPivasAdvice != null)
                {
                    int count = lPivasAdvice.Count;
                    if (count > 1)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            _drugCodes.drugCodes.Add(lPivasAdvice[i].DRUG_CODE);
                        }
                        _drugCodes.reValue = 1;
                        return _drugCodes;
                    }
                    else if (count == 1)
                    {
                        string err = "ERR-医嘱无效，请确认医嘱对接数据！";//无效条码
                        _drugCodes.reValue = 0;
                        _drugCodes.reMsg = err;

                        return _drugCodes;
                    }
                    else
                    {
                        string err = "ERR-本地不存在该医嘱";//不存在该医嘱
                        _drugCodes.reValue = 0;
                        _drugCodes.reMsg = err;

                        return _drugCodes;
                    }
                }
                else
                {
                    string err = "ERR-本地不存在该医嘱";//不存在该医嘱
                    _drugCodes.reValue = 0;
                    _drugCodes.reMsg = err;

                    return _drugCodes;
                }
            }
            catch (Exception e)
            {
                LogHelper.Warn("通过瓶贴号获取条码出现异常：" + e.Message);

                string err = ("ERR-查询医嘱出现异常！");
                _drugCodes.reValue = 0;
                _drugCodes.reMsg = err;

                return _drugCodes;
            }
        }

        public CDrugCodes GetLoacalNotExistDrugCodes(string barCode)
        {
            CDrugCodes drugCodes = new CDrugCodes();
            CDrugCodes _notExitDrugCodes = new CDrugCodes();

            drugCodes = GetAllDrugCode(barCode);
            if (drugCodes.reValue == 0)
            {
                return drugCodes;
            }
            else
            {
                int count = drugCodes.drugCodes.Count;
                for (int i = 0; i < count; i++)
                {
                    string drugCode = drugCodes.drugCodes[i];
                    bool exist = _drugsRepository.IsExistByCode(drugCode);
                    if (false == exist)
                    {
                        //本地不存在
                        _notExitDrugCodes.drugCodes.Add(drugCode);
                    }
                }
                _notExitDrugCodes.reValue = 1;
                return _notExitDrugCodes;
            }
        }

        public List<string> GetAllDrugCodeByBarCode(string barCode)
        {
            List<string> drugCodes = new List<string>();
            try
            {
                List<DTO_adi_advice_drug> lPivasAdvice = _adviceDrug.GetAdviceDrugByGroupNo(barCode);
                if (lPivasAdvice != null)
                {
                    int count = lPivasAdvice.Count;
                    if (count > 1)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            drugCodes.Add(lPivasAdvice[i].DRUG_CODE);
                        }
                        return drugCodes;
                    }
                    else if (count == 1)
                    {
                        string err = "ERR-医嘱无效，请确认医嘱对接数据！";//无效条码
                        drugCodes.Add(err);
                        return drugCodes;
                    }
                    else
                    {
                        string err = "ERR-本地不存在该医嘱";//不存在该医嘱
                        drugCodes.Add(err);
                        return drugCodes;
                    }
                }
                else
                {
                    string err = "ERR-本地不存在该医嘱";//不存在该医嘱
                    drugCodes.Add(err);
                    return drugCodes;
                }
            }
            catch (Exception e)
            {
                LogHelper.Warn("通过瓶贴号获取条码出现异常：" + e.Message);
                drugCodes = new List<string>();
                drugCodes.Add("ERR-查询医嘱出现异常！");
                return drugCodes;
            }
        }

        public List<string> GetNotExistDrugByBarCode(string barCode)
        {
            string drugCode = "";
            List<string> listDrugCodes = new List<string>();
            List<string> relistDrugCodes = new List<string>();
            listDrugCodes = GetAllDrugCodeByBarCode(barCode);
            if (listDrugCodes.Count == 1)
            {
                drugCode = listDrugCodes[0];
                relistDrugCodes.Add(drugCode);
                return relistDrugCodes;
            }
            else
            {
                int count = listDrugCodes.Count;
                for (int i = 0; i < count; i++)
                {
                    drugCode = listDrugCodes[i];
                    bool exist = _drugsRepository.IsExistByCode(drugCode);
                    if (false == exist)
                    {
                        //本地不存在
                        relistDrugCodes.Add(drugCode);
                    }
                }
                return relistDrugCodes;
            }
        }

        ///<summary>
        /// 希尔排序
        ///</summary>
        ///<param name="list"></param>
        private static void ShellSort(List<int> list)
        {
            //取增量
            int step = list.Count / 2;
            while (step >= 1)
            {
                //无须序列
                for (int i = step; i < list.Count; i++)
                {
                    var temp = list[i];
                    int j;
                    //有序序列
                    for (j = i - step; j >= 0 && temp < list[j]; j = j - step)
                    {
                        list[j + step] = list[j];
                    }
                    list[j + step] = temp;
                }
                step = step / 2;
            }
        }

        //冒泡排序算法
        private void bubbleSort(int[] list)
        {
            {
                int i, j, temp;
                bool done = false;
                j = 1;
                while ((j < list.Length) && (!done))
                {
                    done = true;
                    for (i = 0; i < list.Length - j; i++)
                    {
                        if (list[i] > list[i + 1])
                        {
                            done = false;
                            temp = list[i];
                            list[i] = list[i + 1];
                            list[i + 1] = temp;
                        }
                    }
                    j++;
                }
            }
        }

        private List<DTO_adi_dic_drug> bubbleSort(List<DTO_adi_dic_drug> list)
        {
            {
                int i, j;
                bool done = false;
                j = 1;
                while ((j < list.Count) && (!done))
                {
                    done = true;
                    for (i = 0; i < list.Count - j; i++)
                    {
                        if (list[i].BOTTLE_VOLUME > list[i + 1].BOTTLE_VOLUME)
                        {
                            done = false;
                            DTO_adi_dic_drug temp = list[i];
                            list[i] = list[i + 1];
                            list[i + 1] = temp;
                        }
                    }
                    j++;
                }
            }
            return list;
        }

        private static void ShellSort(List<DTO_adi_dic_drug> list)
        {
            //取增量
            int step = list.Count / 2;
            while (step >= 1)
            {
                //无须序列
                for (int i = step; i < list.Count; i++)
                {
                    var temp = list[i];
                    int j;
                    //有序序列
                    for (j = i - step; j >= 0 && temp.BOTTLE_VOLUME > list[j].BOTTLE_VOLUME; j = j - step)
                    {
                        list[j + step] = list[j];
                    }
                    list[j + step] = temp;
                }
                step = step / 2;
            }
        }

        public int GetAdviceCount(string barCode)
        {
            try
            {
                List<DTO_adi_advice_execute> ladviceExcute = _adviceExecute.GetAdviceExcuteByBottleNum(barCode);
                if (ladviceExcute.Count == 1)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Warn("GetAdviceCount 函数出现异常：" + ex.Message);
            }
            return 0;
        }

        public int GetAllAdviceCount()
        {
            try
            {
                //DateTime dt = DateTime.Now;
                //int count = dis_Advice.Context.DTO_adi_advice_execute.Where(ar => ar.EXECUTE_DATE.Date == dt.Date).Count();
                int count = _adviceExecute.GetAdviceExecuteCountOfCurrentDay();
                return count;
            }
            catch (Exception ex)
            {
                LogHelper.Warn("GetAllAdviceCount 函数出现异常：" + ex.Message);
            }
            return 0;
        }

        public List<DTO_adi_dic_drug> GetDrugByCode(string drugCode)
        {
            try
            {
                return _drugsRepository.SearchDrugsByDrugCode(drugCode);
            }
            catch (Exception ex)
            {
                LogHelper.Warn("GetDrugByCode 函数出现异常：" + ex.Message);
            }
            return new List<DTO_adi_dic_drug>();
        }
    }

    public class AdvicePatientItemEqualityComparer : IEqualityComparer<DTO_adi_advice_execute>
    {
        public bool Equals(DTO_adi_advice_execute x, DTO_adi_advice_execute y)
        {
            return (x.ADVICE_GROUP_NO) == (y.ADVICE_GROUP_NO);
        }

        public int GetHashCode(DTO_adi_advice_execute obj)
        {
            return (obj.ADVICE_GROUP_NO).GetHashCode();
        }
    }

    public class AdviceDrugItemEqualityComparer : IEqualityComparer<DTO_adi_advice_drug>
    {
        public bool Equals(DTO_adi_advice_drug x, DTO_adi_advice_drug y)
        {
            return (x.ADVICE_GROUP_NO + "_" + x.DRUG_CODE.Trim()) == (y.ADVICE_GROUP_NO + "_" + y.DRUG_CODE.Trim());
        }

        public int GetHashCode(DTO_adi_advice_drug obj)
        {
            return (obj.ADVICE_GROUP_NO + "_" + obj.DRUG_CODE.Trim()).GetHashCode();
        }
    }

    public class CDrugCodes
    {
        public int reValue { get; set; }
        public string reMsg { get; set; } = "";
        public List<string> drugCodes { get; set; } = new List<string>();
    }
}